package http

import (
	"log"
	"sync"
	"time"
)

// BandwidthAdapter 智能带宽适配器
type BandwidthAdapter struct {
	mutex sync.RWMutex

	// 当前分片大小
	currentChunkSize uint64

	// 性能统计
	successCount   int64
	timeoutCount   int64
	totalWriteTime time.Duration
	totalBytes     int64
	lastAdjustTime time.Time

	// 配置
	minChunkSize   uint64        // 最小分片
	maxChunkSize   uint64        // 最大分片
	adjustInterval time.Duration // 调整间隔

	// 带宽估算
	estimatedBandwidth float64 // KB/s

	// 🚀 新增：趋势检测
	lastBandwidth float64
	increaseCount int // 连续带宽增长次数
	decreaseCount int // 连续带宽下降次数
}

// NewBandwidthAdapter 创建带宽适配器
func NewBandwidthAdapter() *BandwidthAdapter {
	return &BandwidthAdapter{
		currentChunkSize:   512 * 1024,      // 🚀 512KB初始分片（更积极的起点）
		minChunkSize:       64 * 1024,       // 🚀 降低到64KB（支持极慢网络）
		maxChunkSize:       4096 * 1024,     // 🚀 提升到4MB（支持极快网络）
		adjustInterval:     2 * time.Second, // 🚀 2秒快速调整（更快响应网络变化）
		lastAdjustTime:     time.Now(),
		estimatedBandwidth: 0,
		lastBandwidth:      0,
		increaseCount:      0,
		decreaseCount:      0,
	}
}

// GetChunkSize 获取当前建议的分片大小
func (ba *BandwidthAdapter) GetChunkSize() uint64 {
	ba.mutex.RLock()
	defer ba.mutex.RUnlock()
	return ba.currentChunkSize
}

// RecordSuccess 记录成功发送
func (ba *BandwidthAdapter) RecordSuccess(bytes int64, duration time.Duration) {
	ba.mutex.Lock()
	defer ba.mutex.Unlock()

	ba.successCount++
	ba.totalBytes += bytes
	ba.totalWriteTime += duration

	// 定期调整分片大小
	if time.Since(ba.lastAdjustTime) >= ba.adjustInterval {
		ba.adjustChunkSize()
	}
}

// RecordTimeout 记录超时
func (ba *BandwidthAdapter) RecordTimeout() {
	ba.mutex.Lock()
	defer ba.mutex.Unlock()

	ba.timeoutCount++

	// 超时立即调整（降低分片大小）
	ba.adjustChunkSizeOnTimeout()
}

// adjustChunkSize 根据性能调整分片大小
func (ba *BandwidthAdapter) adjustChunkSize() {
	if ba.successCount == 0 {
		return
	}

	// 计算平均带宽 (KB/s)
	if ba.totalWriteTime > 0 {
		avgBandwidth := float64(ba.totalBytes) / ba.totalWriteTime.Seconds() / 1024
		ba.estimatedBandwidth = avgBandwidth

		// 🚀 检测带宽趋势（是增长还是下降）- 更灵敏
		bandwidthTrend := "稳定"
		if ba.lastBandwidth > 0 {
			change := (avgBandwidth - ba.lastBandwidth) / ba.lastBandwidth
			if change > 0.05 { // 🔥 降低到5%（更灵敏）
				ba.increaseCount++
				ba.decreaseCount = 0
				bandwidthTrend = "增长"
			} else if change < -0.05 { // 🔥 降低到5%（更灵敏）
				ba.decreaseCount++
				ba.increaseCount = 0
				bandwidthTrend = "下降"
			} else {
				ba.increaseCount = 0
				ba.decreaseCount = 0
			}
		}
		ba.lastBandwidth = avgBandwidth

		// 🚀🚀🚀 新策略：AIMD算法（Additive Increase Multiplicative Decrease）
		// 类似TCP拥塞控制，更适合网络传输优化
		var idealChunkSize uint64
		oldSize := ba.currentChunkSize

		// 计算超时率
		timeoutRatio := 0.0
		if ba.successCount+ba.timeoutCount > 0 {
			timeoutRatio = float64(ba.timeoutCount) / float64(ba.successCount+ba.timeoutCount)
		}

		// 🔥 核心优化：根据带宽趋势和超时率动态调整（更激进的策略）
		if timeoutRatio > 0.12 { // 🔥 降低阈值到12%（更早响应拥塞）
			// 🔴 乘性降低（快速响应拥塞）
			idealChunkSize = oldSize * 5 / 10 // 🔥 降低50%（更激进）
			log.Printf("⚠️  [带宽适配] 检测到网络拥塞(超时率=%.1f%%)，快速降低分片", timeoutRatio*100)
		} else if timeoutRatio > 0.03 { // 🔥 降低阈值到3%（更灵敏）
			// 🟡 保守增长或小幅降低
			if ba.increaseCount >= 1 { // 🔥 只需1次增长即可尝试增加
				idealChunkSize = oldSize + 128*1024 // 🔥 增加128KB（更积极）
			} else {
				idealChunkSize = oldSize * 85 / 100 // 降低15%
			}
		} else { // 超时率<3%，网络良好
			// 🚀🚀🚀 核心优化：更激进的增长策略

			if bandwidthTrend == "增长" {
				// 🟢 带宽增长：更激进的分片增加
				if avgBandwidth < 50 { // 极慢速网络
					idealChunkSize = oldSize * 14 / 10 // 🔥 增加40%
				} else if avgBandwidth < 150 { // 慢速网络
					idealChunkSize = oldSize * 16 / 10 // 🔥 增加60%
				} else if avgBandwidth < 400 { // 中速网络
					idealChunkSize = oldSize * 18 / 10 // 🔥 增加80%
				} else if avgBandwidth < 1000 { // 中高速网络
					idealChunkSize = oldSize * 22 / 10 // 🔥 增加120%
				} else { // 极速网络
					idealChunkSize = oldSize * 25 / 10 // 🔥 增加150%
				}

				// 🔥 首次增长即激进（不再需要连续2次）
				if ba.increaseCount >= 1 {
					idealChunkSize = oldSize * 22 / 10 // 增加120%
					log.Printf("🚀 [带宽适配] 检测到增长趋势(连续%d次)，激进提升分片", ba.increaseCount)
				}
			} else if bandwidthTrend == "下降" {
				// 🔴 带宽下降：温和降低（避免过度反应）
				idealChunkSize = oldSize * 85 / 100 // 降低15%
			} else {
				// 🟡 带宽稳定：小幅增长（探测更高带宽）
				idealChunkSize = oldSize * 105 / 100 // 🔥 稳定时也增加5%（持续探测）
			}
		}

		// 限制范围
		if idealChunkSize < ba.minChunkSize {
			idealChunkSize = ba.minChunkSize
		}
		if idealChunkSize > ba.maxChunkSize {
			idealChunkSize = ba.maxChunkSize
		}

		// 更新分片大小
		ba.currentChunkSize = idealChunkSize

		log.Printf("🔧 [带宽适配] 调整分片: %d KB -> %d KB | 带宽: %.2f KB/s (%s) | 成功: %d, 超时: %d (%.1f%%)",
			oldSize/1024, ba.currentChunkSize/1024, avgBandwidth, bandwidthTrend,
			ba.successCount, ba.timeoutCount, timeoutRatio*100)
	}

	// 重置统计
	ba.successCount = 0
	ba.timeoutCount = 0
	ba.totalWriteTime = 0
	ba.totalBytes = 0
	ba.lastAdjustTime = time.Now()
}

// adjustChunkSizeOnTimeout 超时时立即降低分片大小
func (ba *BandwidthAdapter) adjustChunkSizeOnTimeout() {
	oldSize := ba.currentChunkSize

	// 🚀 优化：更激进的即时降低策略（降低40%）
	// 超时说明当前分片过大，需要快速调整
	newSize := ba.currentChunkSize * 6 / 10
	if newSize < ba.minChunkSize {
		newSize = ba.minChunkSize
	}

	ba.currentChunkSize = newSize

	// 重置增长计数，因为网络可能出现问题
	ba.increaseCount = 0
	ba.decreaseCount++

	log.Printf("⚠️  [带宽适配] 检测到超时，立即降低分片: %d KB -> %d KB (降低40%%)",
		oldSize/1024, newSize/1024)

	// 不要重置统计！保留已有数据，让正常调整逻辑继续工作
	// 这样可以避免因为偶尔超时而丢失有价值的性能数据
	ba.timeoutCount++ // 只增加超时计数
}

// GetStats 获取统计信息
func (ba *BandwidthAdapter) GetStats() (chunkSize uint64, bandwidth float64) {
	ba.mutex.RLock()
	defer ba.mutex.RUnlock()
	return ba.currentChunkSize, ba.estimatedBandwidth
}

// 全局带宽适配器
var globalBandwidthAdapter = NewBandwidthAdapter()

// GetAdaptiveChunkSize 获取自适应分片大小
func GetAdaptiveChunkSize() uint64 {
	return globalBandwidthAdapter.GetChunkSize()
}
